﻿using Microsoft.WindowsAzure.Storage.Blob;
using PetkaWebDav.Server.Framework.Classes;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace PetkaWebDav.Handler.AzureBlob
{
    public static class RequestWrapper
    {
        private static CloudBlobManager _cloudManager = null;
        //private static String _container = "wordstorage";

        /// <summary>
        /// Private constructor
        /// </summary>
        static RequestWrapper()
        {
            if (_cloudManager == null)
            {
                _cloudManager = new CloudBlobManager(Settings.AzureConnectionString, Settings.AzureContainerName);
            }
        }
        
        #region Internal Methods
        /// <summary>
        /// Retrieve's a file's lock information or loads a locked file (*.locked)
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        internal static DavLockProperty GetLockInfo(string filePath)
        {
            DavLockProperty _lockProperty = null;

            //Try to deserialize the lock file
            CloudBlockBlob _lockFile = GetLockFileByFileName(filePath);
            if (_lockFile != null)
            {
                try
                {
                    using (MemoryStream _lockFileStream = _cloudManager.DownloadBlob(_lockFile.Name))
                    {
                        _lockFileStream.Position = 0;
                        BinaryFormatter _binaryFormatter = new BinaryFormatter();
                        _lockProperty = (DavLockProperty)_binaryFormatter.Deserialize(_lockFileStream);
                        _lockFileStream.Close();
                    }
                }
                catch (Exception)
                {
                    //Incase the deserialization fails
                }
            }

            return _lockProperty;
        }

        /// <summary>
        /// Retrieve's a file's lock information file path (*.locked)
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        internal static CloudBlockBlob GetLockFileByFileName(string filePath)
        {
            //Retrieve a reference to a container. 
            return _cloudManager.GetBlobLockInfoByFileName(filePath);
        }


        /// <summary>
        /// Download Azure Blob File
        /// </summary>
        /// <param name="urlPath">File Name</param>
        /// <returns></returns>
        internal static MemoryStream DownloadBlob(string urlPath)
        {
            return _cloudManager.DownloadBlob(urlPath);
        }

        /// <summary>
        /// Verifies the requested resource is valid
        /// </summary>
        /// <param name="urlPath">Absolute or relative URL path</param>
        /// <returns></returns>
        internal static bool ValidResourceByPath(string urlPath)
        {
            return _cloudManager.FileExist(urlPath);
        }

        /// <summary>
        /// Delete Azure Blob File
        /// </summary>
        /// <param name="_filePath">Blob File Name</param>
        internal static void DeleteAzureFile(string _filePath)
        {
            _cloudManager.DeleteBlob(_filePath);
        }

        /// <summary>
        /// Add Azure Blob File
        /// </summary>
        /// <param name="_filePath">Name for the blob</param>
        /// <param name="_stream">MemoryStream containing file</param>
        internal static void UploadBlob(string _filePath, MemoryStream stream)
        {
            _cloudManager.UploadBlob(stream, _filePath);
        }

        /// <summary>
        /// Returns a lock file based on the lock token GUID
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        internal static CloudBlockBlob GetLockFileByLockToken(string guid)
        {
            return _cloudManager.GetBlobLockInfoByGuid(guid);
        }

        /// <summary>
        /// Retrieves Blobs Info
        /// </summary>
        /// <param name="fileName">Filename to retrieve attributes for</param>
        /// <returns>Null if the file does not exist</returns>
        internal static CloudBlockBlob DownloadBlobAttributes(string fileName)
        {
            return _cloudManager.DownloadBlobAttributes(fileName);
        }
        #endregion
    }
}
